// MicroIRCd

#include "deps.h"
#include "server.h"
#include "functions.h"

client_t clients[MAX_CLIENTS];

int str_split(char **arr, char *str, char *d)
{
    int n = 0;
    char *pch = strtok(str, d);
    while (pch != NULL)
    {
        arr[n++] = pch;
        pch = strtok(NULL, d);
    }
    arr[n] = 0;
    return n;
}

int CL_COUNT(char *list)
{
    int i = 1;
    char *p = list;
    while ((p = strchr(p, ' ')))
    {
        p++;
        i++;
    }
    return i;
}

char *strchr_n(char *str, int n)
{
    char *p = str;
    while ((p = strchr(p, ' ')) && n--)
        if (p)
            p++;
    return p;
}

char *CL_HEAD(char *list, int n)
{
    if (list)
    {
        static char buf[BUF_SIZE];
        char *p = strchr_n(list, n - 1);
        int len = p ? p - list : n ? (int) strlen(list) : 0;
        memcpy(buf, list, len);
        buf[len] = 0;
        return buf;
    }
    return 0;
}

char *CL_TAIL(char *list, int n)
{
    if (list)
    {
        static char buf[BUF_SIZE];
        char *p = strchr_n(list, n - 1);
        int len = p ? p - list + 1 : n ? (int) strlen(list) : 0;
        memcpy(buf, list + len, strlen(list) - len);
        buf[strlen(list) - len] = 0;
        return buf;
    }
    return 0;
}

char *CL_ITEM(char *list, int n)
{
    return CL_HEAD(CL_TAIL(list, n), 1);
}

int CL_ISSET(char *list, char *key)
{
    int i;
    char *arr[BUF_SIZE];
    char buf[BUF_SIZE];
    int count;
    strcpy(buf, list);
    count = str_split(arr, buf, " ");
    for (i = 0; i < count; i++)
    {
        if (strcmp(arr[i], key) == 0)
            return 1;
    }
    return 0;
}

int CL_SET(char *list, char *key)
{
    if (strlen(list) + strlen(key) + 1 >= BUF_SIZE)
        return 0;

    if (!CL_ISSET(list, key))
    {
        if (strlen(list) != 0)
            strcat(list, " ");

        strcat(list, key);
        return 1;
    }
    return 0;
}

int CL_CLR(char *list, char *key)
{
    int i;
    char *arr[1024];
    char buf[1024];
    int count;
    strcpy(buf, list);
    count = str_split(arr, buf, " ");
    list[0] = 0;
    for (i = 0; i < count; i++)
        if (strcmp(arr[i], key) != 0)
            CL_SET(list, arr[i]);
    return 0;
}

int CL_MATCH(char *c1, char *c2)
{
    int i, j, v1, v2;
    char *arr1[BUF_SIZE];
    char *arr2[BUF_SIZE];
    char buf1[BUF_SIZE];
    char buf2[BUF_SIZE];
    strcpy(buf1, c1);
    strcpy(buf2, c2);
    v1 = str_split(arr1, buf1, " ");
    v2 = str_split(arr2, buf2, " ");
    for (j = 0; j < v2; j++)
        for (i = 0; i < v1; i++)
            if (strcmp(arr1[i], arr2[j]) == 0)
                return 1;
    return 0;
}

client_t *get_user_by_nickname(char *nickname)
{
    int i;
    for (i = 0; i < num_clients; i++)
    {
        if (strcmp(nickname, clients[i].nickname) == 0)
            return &clients[i];
    }
    return 0;
}

int get_userlist_by_chan(char *userlist, char *chan)
{
    int i;
    userlist[0] = 0;
    for (i = 0; i < num_clients; i++)
    {
        if (chan == 0 || CL_ISSET(clients[i].chanlist, chan))
            CL_SET(userlist, clients[i].nickname);
    }
    return 0;
}

char *unquote(char *str)
{
    int len = strlen(str);
    if (str[0] == '\"' && str[len - 1] == '\"')
    {
        memmove(str, str + 1, len - 1);
        str[len - 2] = 0;
    }
    return str;
}

void reply(client_t * cl, char *dest, char *fmt, ...)
{
    int j, len;
    char buf[BUF_SIZE];

    va_list ap;
    va_start(ap, fmt);
    vsprintf(buf, fmt, ap);
    va_end(ap);
    strcat(buf, "\n");
    len = strlen(buf);

    if (!dest || !strlen(dest))
    {
        printf("[send %d bytes] %s", len, buf);
        send(cl->sock, buf, len, 0);
    }
    else
    {
        for (j = 0; j < num_clients; j++)
        {
            if ((CL_ISSET(dest, clients[j].nickname) || (CL_MATCH(dest, clients[j].chanlist) && cl->sock != clients[j].sock)))
            {
                printf("[send %d bytes] %s", len, buf);
                send(clients[j].sock, buf, len, 0);
            }
        }
    }
}

int string_to_argv(char **argv, char *str, int size)
{
    int i, argc = 0;
    char *p1 = str;
    char *p2 = str;
    argv[argc++] = p2;
    while ((p2 = strchr(p1, ' ')) && argc < size)
    {
        argv[argc++] = p2 + 1;
        p1 = p2 + 1;
        *p2 = 0;
        if (p1[0] == ':')
            break;
    }
    for (i = 0; i < argc; i++)
    {
        unquote(argv[i]);
        if (argv[i][0] == ':')
            argv[i]++;
    }
    return argc;
}

int die(int code)
{
    perror("socket error");
    exit(code);
}
